package main

import "fmt"

// 通过使用 14.12 中工厂函数生成前 10 个斐波那契数

type Any interface{}
type EvalFunc func(Any) (Any, Any)

func BuildLazyEvaluator(evalFunc EvalFunc, initState Any) func() Any {
	ch := make(chan Any)
	loopFunc := func() {
		var actState Any = initState
		var retState Any
		for {
			retState, actState = evalFunc(actState)
			ch <- retState
		}
	}
	go loopFunc()
	return func() Any {
		return <-ch
	}
}

func BuildLazyFibonacciEvaluator(e EvalFunc, s Any) func() uint64 {
	ef := BuildLazyEvaluator(e, s)
	return func() uint64 {
		return ef().(uint64)
	}
}

func main() {
	genFibonacci := makeFibonacciGen()

	fmt.Println(genFibonacci())
	fmt.Println(genFibonacci())
	fmt.Println(genFibonacci())
	fmt.Println(genFibonacci())
	fmt.Println(genFibonacci())
	fmt.Println(genFibonacci())

	fmt.Println("===== used lazyBuilder =====")
	// state = []uint64{a, b}
	fiboEvalFunc := func(state Any) (Any, Any) {
		// 类型转化
		s := state.([]uint64)
		a, b := s[0], s[1]

		return b, []uint64{b, a + b}
	}
	fiboGen := BuildLazyFibonacciEvaluator(fiboEvalFunc, []uint64{0, 1})
	fmt.Println(fiboGen())
	fmt.Println(fiboGen())
	fmt.Println(fiboGen())
	fmt.Println(fiboGen())
	fmt.Println(fiboGen())
	fmt.Println(fiboGen())

}

func makeFibonacciGen() func() uint64 {
	ch := make(chan uint64)
	loopFunc := func() {
		var a, b uint64 = 0, 1
		for {
			a, b = b, a+b
			ch <- a
		}
	}
	go loopFunc()
	return func() uint64 {
		return <-ch
	}
}
